package myJs.tools

import myJs.Implicits._
import myJs.Utils
import myJs.Utils._
import myJs.myPkg._
import myJs.myPkg.jquery._
import myJs.tool.Tool
import org.scalajs.dom._
import org.scalajs.dom.ext.Ajax
import org.scalajs.dom.raw.HTMLFormElement
import scalatags.Text.all
import scalatags.Text.all._

import scala.collection.immutable.SeqMap
import scala.concurrent.ExecutionContext.Implicits.global
import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}

/**
 * Created by yz on 16/9/2021
 */
@JSExportTopLevel("Caps")
object Caps {

  val formId = "form"

  def formJq = $(s"#${formId}")

  @JSExport("init")
  def init = {
    Tool.fileInput
    Tool.popover
    refreshQueryType
    refreshRadio
    bootStrapValidator
    registerEvent
  }

  def refreshQueryType = {
    val names = List("Text", "File")
    val html = names.zipWithIndex.map { case (vsName, i) =>
      label(
        marginRight := 15,
        width := 200,
      )(input(
        `class` := "myMethod",
        `type` := "radio",
        name := "method",
        value := vsName,
        if (i == 0) checked else all.raw(""),
      )(vsName)
      )
    }.mkString
    formJq.find(s"#queryType").empty().html(html)
  }

  def refreshRadio = {
    refreshPloidy
    refreshCaps
    refreshKasp
    refreshPickAnyway
  }

  def refreshPloidy = {
    val nameStr = "ploidy"
    val map = SeqMap("1" -> "A genome", "2" -> "AB genome", "3" -> "ABD genome")
    val selectV = "3"
    val html = map.zipWithIndex.map { case ((v, showName), i) =>
      label(
        marginRight := 15,
        width := 200,
      )(input(
        `type` := "radio",
        name := nameStr,
        value := v,
        if (v == selectV) checked else all.raw(""),
      )(showName)
      )
    }.mkString
    formJq.find(s"#ploidy").empty().html(html)
  }

  def refreshCaps = {
    val nameStr = "caps"
    val map = SeqMap("1" -> "Yes", "0" -> "No")
    val selectV = "1"
    val widthDb = 100
    val html = map.zipWithIndex.map { case ((v, showName), i) =>
      label(
        marginRight := 15,
        width := widthDb,
      )(input(
        `type` := "radio",
        name := nameStr,
        value := v,
        if (v == selectV) checked else all.raw(""),
      )(showName)
      )
    }.mkString
    formJq.find(s"#${nameStr}").empty().html(html)
  }

  def refreshKasp = {
    val nameStr = "kasp"
    val map = SeqMap("1" -> "Yes", "0" -> "No")
    val selectV = "1"
    val widthDb = 100
    val html = map.zipWithIndex.map { case ((v, showName), i) =>
      label(
        marginRight := 15,
        width := widthDb,
      )(input(
        `type` := "radio",
        name := nameStr,
        value := v,
        if (v == selectV) checked else all.raw(""),
      )(showName)
      )
    }.mkString
    formJq.find(s"#${nameStr}").empty().html(html)
  }

  def refreshPickAnyway = {
    val nameStr = "pickAnyway"
    val map = SeqMap("1" -> "Yes", "0" -> "No")
    val selectV = "1"
    val widthDb = 100
    val html = map.zipWithIndex.map { case ((v, showName), i) =>
      label(
        marginRight := 15,
        width := widthDb,
      )(input(
        `type` := "radio",
        name := nameStr,
        value := v,
        if (v == selectV) checked else all.raw(""),
      )(showName)
      )
    }.mkString
    formJq.find(s"#${nameStr}").empty().html(html)
  }

  def registerEvent = {
    $(document.body).on("click", s".myRun", "", (y: Element) => {
      myRun
    })
    $(document.body).on("click", s".myShowExample", "", (y: Element) => {
      showExample(y)
    })
    $(document.body).on("change", s".myMethod", "", (y: Element) => {
      methodChange(y)
    })
    $(document.body).on("click", s".myShowExampleFile", "", (y: Element) => {
      showExampleFile
    })
    $(document.body).on("click", s".myDownloadPre", "", (y: Element) => {
      downloadPre(y)
    })
  }

  def downloadPre(y: Element) = {
    val fileName = $(y).dataValue
    val content = $(y).parents(".myPre").find("pre").html()
    Tool.downloadTxt(fileName, content)
  }

  def methodChange(y: Element) = {
    val value = $(y).myVal
    $(".eachMethod").hide()
    $(s"#${value.toLowerCase}").show()
  }

  val eg =
    s"""
       |e1,7,GGGACCTCATGGGGGAGCATCTGAGCAGGGCTGGGATGAATGAGGAGACACCAGCAAAGAGGATGTTGAGAACAATTCCTGGGGAGAAAA[A/T]TGTGGTCTCATTACCTCATTCGAAGTGGCCTGATCTCAAGGAAGCAGGGAGCAGAGAAACATAATCGGAACATCTCTGTGCATCAGGTTTTCGTACTGACCGTGAAGCACCAAGTGGAAGCAAGCCTCGCGCTGGGAGGACAAGGCTCT
       |e2,7,CGGCGTTTCCTTGTGGATTTATTTGCTCAGCATGAGTGCCCTGTCAAGCCACCCAAGGGACAGAGCTTCTGGCTCAGGGACCACGGTTGGC[C/T]CAGCACAGGCAGCCTCTGGAGATGAGAGGGAACCAGTGGATACCCTTCTATCCCTGCTGGCCACGAGGGGTGGCAGTGTCCCAGGTAGAGGTACTTAATAAAGAGGTTGCTGGTTTTATTTTTCTCTAAATTATTTTTCGAGGAGCTT
       |e3,7,TTCCATAAGCCCAGGCCCTGGGTTCACACCATCACTGGGGCAGAAGCCTCTTCCCTGCCTTGTCTGATGGGGTCTTTACACCTTCCTCGGTCA[C/G]TGATGCCAGGTGCTATTGTTCCTGCTCAGCCAATGTCTGGACTGAGTCCCGAGCCTCATTCCATGGGCAGTGGCTCTGTCTCCAGGTGGGGCACATGGAGGCCAAGTCCCAGGGCAGGGCCCACGGTGGGCCTGGTCTTACGGGTG
       |""".stripMargin.trim

  def showExample(y: Element) = {
    val inputJq = $(y).parents(".form-group").find(":input")
    inputJq.`val`(eg)
    inputJq.parents(s"#${formId}").bv.revalidateField(inputJq)
  }

  def showExampleFile = {
    val content = eg
    Tool.downloadCsv("example.csv", content)
  }

  def myRun = {
    val bv = formJq.bv
    val resultJq = $("#result")
    bv.validate()
    val valid = bv.isValid()
    if (valid) {
      val formData = new FormData(document.getElementById(formId).asInstanceOf[HTMLFormElement])
      val element = div(id := "content",
        span(id := "info", "Running...",
          span(id := "progress")), " ",
        img(src := "/assets/images/running2.gif", cls := "runningImage", width := 30, height := 20)
      ).render
      val layerOptions = LayerOptions.icon(16).shade(0.01).time(20000000)
      val index = layer.msg(element, layerOptions)
      val url = g.jsRoutes.controllers.ToolsController.caps().url.toString
      val xhr = new XMLHttpRequest
      xhr.open("post", url)
      xhr.upload.onprogress = Utils.progressHandlingFunction
      xhr.onreadystatechange = (e) => {
        if (xhr.readyState == XMLHttpRequest.DONE) {
          layer.close(index)
          val rs = xhr.responseText.toJDJAn
          val valid = rs("valid").toB
          if (valid) {
            resultJq.find("#alignment").html(rs.myGet("alignment"))
            resultJq.find("#caps").html(rs.myGet("caps"))
            resultJq.find("#kasp").html(rs.myGet("kasp"))
            resultJq.show()
            val target_top = $("#result").offset().top
            $("html,body").animate(js.Dictionary("scrollTop" -> target_top), JQueryAnimationSettings.duration(800))
          } else {
            g.swal("Error", rs.myGet("message"), "error")
            resultJq.hide()
          }
        }
      }
      xhr.send(formData)
    }
  }

  def bootStrapValidator = {
    val dict: js.Dictionary[js.Any] = js.Dictionary(
      "feedbackIcons" -> js.Dictionary(
        "valid" -> "glyphicon glyphicon-ok",
        "invalid" -> "glyphicon glyphicon-remove",
        "validating" -> "glyphicon glyphicon-refresh",
      ),
      "fields" -> js.Dictionary(
        "price" -> {
          val info = "Maximum NEB restriction enzyme price"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info} is required!"
              ),
              "integer" -> js.Dictionary(
                "message" -> s"${info} must be integer！",
              ),
            )
          )
        },
        "maxSize" -> {
          val info = "Maximum Primer Size"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info} is required!"
              ),
              "integer" -> js.Dictionary(
                "message" -> s"${info} must be integer！",
              ),
            )
          )
        },
        "maxTm" -> {
          val info = "Max primer TM"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info} is required!"
              ),
              "integer" -> js.Dictionary(
                "message" -> s"${info} must be integer！",
              ),
            )
          )
        },
        "queryText" -> {
          val info = "FASTA sequences"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info} is required!"
              ),
            )
          )
        },
        "file" -> {
          val info = "Query file"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "file" -> js.Dictionary(
                "message" -> s"${info} must is a csv file！",
                "extension" -> "csv",
              ),
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info} is required!"
              ),
            )
          )
        },
      )
    )
    formJq.bootstrapValidator(dict)
  }

}
